#include "service/auth/auth_service.h"
#include <openssl/sha.h>
#include <openssl/rand.h>
#include <openssl/evp.h>  // 使用EVP接口代替直接哈希函数
#include <sstream>
#include <iomanip>
#include <ctime>
#include <uuid/uuid.h>

namespace service {
namespace auth {

// 用户转换为JSON
nlohmann::json User::toJson() const {
    nlohmann::json json;
    json["id"] = id;
    json["username"] = username;
    json["nickname"] = nickname;
    json["email"] = email;
    json["avatar"] = avatar;
    json["created_at"] = createdAt;
    json["last_login"] = lastLogin;
    json["status"] = status;
    // 不包含密码和盐值等敏感信息
    return json;
}

// 从JSON构造用户
User User::fromJson(const nlohmann::json& json) {
    User user;
    user.id = json.value("id", 0);
    user.username = json.value("username", "");
    user.nickname = json.value("nickname", "");
    user.email = json.value("email", "");
    user.passwordHash = json.value("password_hash", "");
    user.salt = json.value("salt", "");
    user.avatar = json.value("avatar", "");
    user.createdAt = json.value("created_at", "");
    user.lastLogin = json.value("last_login", "");
    user.status = json.value("status", 1);
    return user;
}

// 创建认证服务实例
std::shared_ptr<AuthService> AuthService::create(
    std::shared_ptr<database::MySQLPool> dbPool,
    std::shared_ptr<cache::RedisClient> redisClient) {
    return std::shared_ptr<AuthService>(new AuthService(dbPool, redisClient));
}

// 构造函数
AuthService::AuthService(std::shared_ptr<database::MySQLPool> dbPool,
                       std::shared_ptr<cache::RedisClient> redisClient)
    : dbPool_(dbPool), redisClient_(redisClient), isRunning_(false) {
}

// 启动服务
bool AuthService::start(int port) {
    if (isRunning_) {
        return false;
    }
    
    // 创建EpollServer，使用正确的构造函数
    server_ = std::make_unique<network::EpollServer>(port);
    
    // 设置回调函数
    server_->setConnectionCallback(
        std::bind(&AuthService::handleConnection, this, std::placeholders::_1));
    server_->setMessageCallback(
        std::bind(&AuthService::handleMessage, this, std::placeholders::_1, std::placeholders::_2));
    server_->setCloseCallback(
        std::bind(&AuthService::handleClose, this, std::placeholders::_1));
    
    // 启动服务器，不需要传入端口参数
    server_->start();
    
    isRunning_ = true;
    return true;
}

// 停止服务
void AuthService::stop() {
    if (!isRunning_) {
        return;
    }
    
    server_->stop();
    isRunning_ = false;
}

// 处理新连接
void AuthService::handleConnection(std::shared_ptr<network::Connection> conn) {
    // 记录连接信息，可以在这里做一些初始化工作
    (void)conn; // 避免未使用参数警告
}

// 处理客户端消息
void AuthService::handleMessage(std::shared_ptr<network::Connection> conn, const std::string& message) {
    // 解析JSON消息
    nlohmann::json root;
    
    try {
        root = nlohmann::json::parse(message);
    } catch(const std::exception& e) {
        // 解析失败，返回错误信息
        nlohmann::json response;
        response["status"] = "error";
        response["message"] = "Invalid JSON format";
        conn->send(response.dump());
        return;
    }
    
    // 获取请求路径、方法和参数
    std::string path = root.value("path", "");
    std::string method = root.value("method", "GET");
    nlohmann::json params = root.value("params", nlohmann::json());
    
    // 处理请求
    std::string responseStr = handleRequest(path, method, params);
    conn->send(responseStr);
}

// 处理连接关闭
void AuthService::handleClose(std::shared_ptr<network::Connection> conn) {
    // 清理连接相关资源
    (void)conn; // 避免未使用参数警告
}

// 处理API请求
std::string AuthService::handleRequest(const std::string& path, const std::string& method, 
                                    const nlohmann::json& params) {
    nlohmann::json response;
    
    try {
        if (path == "/api/auth/register" && method == "POST") {
            // 注册用户
            std::string username = params.value("username", "");
            std::string password = params.value("password", "");
            std::string email = params.value("email", "");
            std::string nickname = params.value("nickname", username);
            
            if (username.empty() || password.empty() || email.empty()) {
                response["status"] = "error";
                response["message"] = "Missing required fields";
            } else {
                int userId = registerUser(username, password, email, nickname);
                if (userId > 0) {
                    response["status"] = "success";
                    response["user_id"] = userId;
                } else {
                    response["status"] = "error";
                    response["message"] = "Registration failed";
                }
            }
        } else if (path == "/api/auth/login" && method == "POST") {
            // 用户登录
            std::string username = params.value("username", "");
            std::string password = params.value("password", "");
            
            if (username.empty() || password.empty()) {
                response["status"] = "error";
                response["message"] = "Missing username or password";
            } else {
                std::string token = login(username, password);
                if (!token.empty()) {
                    response["status"] = "success";
                    response["token"] = token;
                    
                    // 获取用户信息
                    User user = getUserByUsername(username);
                    response["user"] = user.toJson();
                } else {
                    response["status"] = "error";
                    response["message"] = "Invalid username or password";
                }
            }
        } else if (path == "/api/auth/verify" && method == "GET") {
            // 验证token
            std::string token = params.value("token", "");
            int userId = 0;
            
            if (verifyToken(token, userId)) {
                response["status"] = "success";
                response["user_id"] = userId;
                
                // 获取用户信息
                User user = getUserById(userId);
                response["user"] = user.toJson();
            } else {
                response["status"] = "error";
                response["message"] = "Invalid token";
            }
        } else if (path == "/api/auth/profile" && method == "GET") {
            // 获取用户信息
            std::string token = params.value("token", "");
            int userId = 0;
            
            if (!verifyToken(token, userId)) {
                response["status"] = "error";
                response["message"] = "Unauthorized";
            } else {
                User user = getUserById(userId);
                response["status"] = "success";
                response["user"] = user.toJson();
            }
        } else if (path == "/api/auth/update" && method == "POST") {
            // 更新用户信息
            std::string token = params.value("token", "");
            int userId = 0;
            
            if (!verifyToken(token, userId)) {
                response["status"] = "error";
                response["message"] = "Unauthorized";
            } else {
                User user = getUserById(userId);
                user.nickname = params.value("nickname", user.nickname);
                user.email = params.value("email", user.email);
                user.avatar = params.value("avatar", user.avatar);
                
                if (updateUser(user)) {
                    response["status"] = "success";
                    response["user"] = user.toJson();
                } else {
                    response["status"] = "error";
                    response["message"] = "Update failed";
                }
            }
        } else if (path == "/api/auth/change_password" && method == "POST") {
            // 修改密码
            std::string token = params.value("token", "");
            int userId = 0;
            
            if (!verifyToken(token, userId)) {
                response["status"] = "error";
                response["message"] = "Unauthorized";
            } else {
                std::string oldPassword = params.value("old_password", "");
                std::string newPassword = params.value("new_password", "");
                
                if (oldPassword.empty() || newPassword.empty()) {
                    response["status"] = "error";
                    response["message"] = "Missing old or new password";
                } else {
                    if (changePassword(userId, oldPassword, newPassword)) {
                        response["status"] = "success";
                    } else {
                        response["status"] = "error";
                        response["message"] = "Password change failed";
                    }
                }
            }
        } else {
            // 未知路径
            response["status"] = "error";
            response["message"] = "Unknown API path";
        }
    } catch (const std::exception& e) {
        // 异常处理
        response["status"] = "error";
        response["message"] = std::string("Server error: ") + e.what();
    }
    
    return response.dump();
}

// 用户注册
int AuthService::registerUser(const std::string& username, const std::string& password,
                            const std::string& email, const std::string& nickname) {
    // 检查用户名是否已存在
    auto conn = dbPool_->getConnection();
    std::string query = "SELECT id FROM users WHERE username = '" + username + "'";
    
    // 使用query方法替代prepareStatement
    auto result = conn->query(query);
    if (!result) {
        return -1;
    }
    
    // 生成盐值和密码哈希
    std::string salt = generateSalt();
    std::string passwordHash = hashPassword(password, salt);
    
    // 获取当前时间
    std::time_t now = std::time(nullptr);
    char timeStr[32];
    std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", std::localtime(&now));
    std::string createdAt = timeStr;
    
    // 插入用户记录
    query = "INSERT INTO users (username, password_hash, salt, email, nickname, created_at, status) "
            "VALUES ('" + username + "', '" + passwordHash + "', '" + salt + "', '" 
            + email + "', '" + nickname + "', '" + createdAt + "', 1)";
    
    if (!conn->query(query)) {
        return -1;
    }
    
    // 获取用户ID
    return conn->getInsertId();
}

// 用户登录
std::string AuthService::login(const std::string& username, const std::string& password) {
    // 获取用户信息
    auto conn = dbPool_->getConnection();
    std::string query = "SELECT id, password_hash, salt, status FROM users WHERE username = '" + username + "'";
    
    auto result = conn->query(query);
    if (!result) {
        return "";
    }
    
    int userId = 0;
    std::string passwordHash;
    std::string salt;
    int status = 0;
    
    // 读取结果集
    // 假设MySQLConnection提供了适当的方法来获取结果
    // 这里需要根据实际API调整
    
    // 检查用户状态
    if (status != 1) {
        // 用户被禁用
        return "";
    }
    
    // 验证密码
    if (hashPassword(password, salt) != passwordHash) {
        // 密码错误
        return "";
    }
    
    // 更新最后登录时间
    std::time_t now = std::time(nullptr);
    char timeStr[32];
    std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", std::localtime(&now));
    
    query = "UPDATE users SET last_login = '" + std::string(timeStr) + "' WHERE id = " + std::to_string(userId);
    conn->query(query);
    
    // 生成token
    std::string token = generateToken(userId);
    
    // 将token存入Redis - 修正参数顺序
    std::string redisKey = "auth:token:" + token;
    std::string redisValue = std::to_string(userId);
    redisClient_->setex(redisKey, redisValue, 86400);  // 24小时有效期
    
    return token;
}

// 验证token
bool AuthService::verifyToken(const std::string& token, int& userId) {
    if (token.empty()) {
        return false;
    }
    
    // 从Redis中获取token对应的用户ID - 修正API使用
    std::string redisKey = "auth:token:" + token;
    std::string value = redisClient_->get(redisKey);
    
    if (value.empty()) {
        return false;
    }
    
    try {
        userId = std::stoi(value);
        return true;
    } catch (const std::exception& e) {
        return false;
    }
}

// 获取用户信息（通过ID）
User AuthService::getUserById(int id) {
    // 先尝试从缓存获取
    User user = getUserFromCache(id);
    if (user.id > 0) {
        return user;
    }
    
    // 从数据库获取
    auto conn = dbPool_->getConnection();
    std::string query = "SELECT * FROM users WHERE id = " + std::to_string(id);
    
    auto result = conn->query(query);
    if (!result) {
        return user;
    }
    
    // 读取结果并填充user对象
    // 这里需要根据实际API调整
    
    // 缓存用户信息
    cacheUser(user);
    
    return user;
}

// 获取用户信息（通过用户名）
User AuthService::getUserByUsername(const std::string& username) {
    // 从数据库获取
    auto conn = dbPool_->getConnection();
    std::string query = "SELECT * FROM users WHERE username = '" + username + "'";
    
    auto result = conn->query(query);
    if (!result) {
        return User();
    }
    
    User user;
    
    // 读取结果并填充user对象
    // 这里需要根据实际API调整
    
    // 缓存用户信息
    cacheUser(user);
    
    return user;
}

// 更新用户信息
bool AuthService::updateUser(const User& user) {
    auto conn = dbPool_->getConnection();
    std::string query = "UPDATE users SET nickname = '" + user.nickname + 
                        "', email = '" + user.email + 
                        "', avatar = '" + user.avatar + 
                        "' WHERE id = " + std::to_string(user.id);
    
    bool success = conn->query(query);
    
    if (success) {
        // 更新缓存
        cacheUser(user);
        return true;
    }
    
    return false;
}

// 修改密码
bool AuthService::changePassword(int userId, const std::string& oldPassword, const std::string& newPassword) {
    // 获取用户信息
    User user = getUserById(userId);
    if (user.id <= 0) {
        return false;
    }
    
    // 验证旧密码
    if (hashPassword(oldPassword, user.salt) != user.passwordHash) {
        return false;
    }
    
    // 生成新的盐值和密码哈希
    std::string newSalt = generateSalt();
    std::string newPasswordHash = hashPassword(newPassword, newSalt);
    
    // 更新密码
    auto conn = dbPool_->getConnection();
    std::string query = "UPDATE users SET password_hash = '" + newPasswordHash + 
                        "', salt = '" + newSalt + 
                        "' WHERE id = " + std::to_string(userId);
    
    bool success = conn->query(query);
    
    if (success) {
        // 更新缓存中的用户信息
        user.passwordHash = newPasswordHash;
        user.salt = newSalt;
        cacheUser(user);
        return true;
    }
    
    return false;
}

// 重置密码
bool AuthService::resetPassword(const std::string& email) {
    // 查找用户
    auto conn = dbPool_->getConnection();
    std::string query = "SELECT id FROM users WHERE email = '" + email + "'";
    
    auto result = conn->query(query);
    if (!result) {
        return false;
    }
    
    int userId = 0; // 应该从结果集中获取
    
    // 生成随机密码
    std::string newPassword = generateSalt().substr(0, 8);
    std::string newSalt = generateSalt();
    std::string newPasswordHash = hashPassword(newPassword, newSalt);
    
    // 更新密码
    query = "UPDATE users SET password_hash = '" + newPasswordHash + 
            "', salt = '" + newSalt + 
            "' WHERE id = " + std::to_string(userId);
    
    bool success = conn->query(query);
    
    if (success) {
        // 发送重置密码邮件（此处省略，实际应该调用邮件服务）
        // TODO: 发送包含新密码的邮件给 email 地址
        
        // 更新缓存
        User user = getUserById(userId);
        user.passwordHash = newPasswordHash;
        user.salt = newSalt;
        cacheUser(user);
        
        return true;
    }
    
    return false;
}

// 生成密码哈希 - 使用EVP接口替代废弃的SHA256函数
std::string AuthService::hashPassword(const std::string& password, const std::string& salt) {
    // 将密码和盐值组合
    std::string combined = password + salt;
    
    // 使用EVP接口
    unsigned char hash[EVP_MAX_MD_SIZE];
    unsigned int hashLen = 0;
    
    EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
    EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
    EVP_DigestUpdate(mdctx, combined.c_str(), combined.length());
    EVP_DigestFinal_ex(mdctx, hash, &hashLen);
    EVP_MD_CTX_free(mdctx);
    
    // 转换为十六进制字符串
    std::stringstream ss;
    for (size_t i = 0; i < hashLen; i++) {
        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
    }
    
    return ss.str();
}

// 生成随机盐值
std::string AuthService::generateSalt() {
    unsigned char bytes[16];
    RAND_bytes(bytes, sizeof(bytes));
    
    std::stringstream ss;
    // 使用size_t代替int避免符号比较警告
    for (size_t i = 0; i < sizeof(bytes); i++) {
        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(bytes[i]);
    }
    
    return ss.str();
}

// 生成token
std::string AuthService::generateToken(int userId) {
    // 使用userId使参数不再未使用
    (void)userId;
    
    uuid_t uuid;
    uuid_generate(uuid);
    
    char uuidStr[37];
    uuid_unparse(uuid, uuidStr);
    
    return std::string(uuidStr);
}

// 从缓存获取用户
User AuthService::getUserFromCache(int id) {
    std::string redisKey = "auth:user:" + std::to_string(id);
    std::string value = redisClient_->get(redisKey);
    
    if (value.empty()) {
        return User();
    }
    
    // 解析JSON
    nlohmann::json json;
    try {
        json = nlohmann::json::parse(value);
    } catch (const std::exception& e) {
        return User();
    }
    
    return User::fromJson(json);
}

// 将用户存入缓存
void AuthService::cacheUser(const User& user) {
    if (user.id <= 0) {
        return;
    }
    
    std::string redisKey = "auth:user:" + std::to_string(user.id);
    nlohmann::json json;
    json["id"] = user.id;
    json["username"] = user.username;
    json["nickname"] = user.nickname;
    json["email"] = user.email;
    json["password_hash"] = user.passwordHash;
    json["salt"] = user.salt;
    json["avatar"] = user.avatar;
    json["created_at"] = user.createdAt;
    json["last_login"] = user.lastLogin;
    json["status"] = user.status;
    
    std::string value = json.dump();
    // 修正参数顺序
    redisClient_->setex(redisKey, value, 3600);  // 1小时有效期
}

} // namespace auth
} // namespace service 